﻿/********************************************************************************
** 作者： Mick
** 邮箱： zheng_jinfan@126.com
** 主页： http://www.zhengjinfan.cn
** 创始时间：2016-2-17
** 描述：
**      [辅助类]图片操作辅助类
*********************************************************************************/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using BestEasyCMS.Framework.Extension;

namespace BestEasyCMS.Framework.Util
{
    /// <summary>
    ///  [辅助类]图片操作辅助类
    /// </summary>
    public sealed class ImageUtil
    {
        #region 构造实例

        /// <summary>
        ///  [辅助类]图片操作辅助类
        /// </summary>
        private ImageUtil()
        {
        }

        /// <summary>
        /// 构建类的实例对象
        /// </summary>
        public static ImageUtil Instance
        {
            get { return new ImageUtil(); }
        }

        #endregion 构造实例

        #region 公共枚举

        #region ThumbnailMode enum

        /// <summary>
        /// 缩略图的模式
        /// </summary>
        public enum ThumbnailMode
        {
            /// <summary>
            /// 指定高宽缩放(可能变形)
            /// </summary>
            Wh,

            /// <summary>
            /// 指定宽，高按比例
            /// </summary>
            W,

            /// <summary>
            /// 指定高，宽按比例
            /// </summary>
            H,

            /// <summary>
            /// 指定高宽裁减(不变形)
            /// </summary>
            Cut,

            /// <summary>
            /// 等比缩放(不变形，如果高大按高，宽大按宽缩放)
            /// </summary>
            Db
        }

        #endregion ThumbnailMode enum

        #region ThumbnailType enum

        /// <summary>
        /// 缩略图保存格式
        /// </summary>
        public enum ThumbnailType
        {
            /// <summary>
            /// JPG格式
            /// </summary>
            Jpg,

            /// <summary>
            /// BMP格式
            /// </summary>
            Bmp,

            /// <summary>
            /// GIF格式
            /// </summary>
            Gif,

            /// <summary>
            /// PNG格式
            /// </summary>
            Png
        }

        #endregion ThumbnailType enum

        #region WatermarkPosition enum

        /// <summary>
        /// 水印位置
        /// </summary>
        public enum WatermarkPosition
        {
            /// <summary>
            /// 水印放置左上角
            /// </summary>
            LeftTop = 1,

            /// <summary>
            /// 水平居中垂直顶部
            /// </summary>
            CenterTop = 2,

            /// <summary>
            /// 右上角
            /// </summary>
            RightTop = 3,

            /// <summary>
            /// 垂直居中水平靠左
            /// </summary>
            LeftMiddle = 4,

            /// <summary>
            /// 居中
            /// </summary>
            CenterMiddle = 5,

            /// <summary>
            /// 垂直居中水平靠右
            /// </summary>
            RightMiddle = 6,

            /// <summary>
            /// 左下角
            /// </summary>
            LeftBottom = 7,

            /// <summary>
            /// 水平居中垂直底部
            /// </summary>
            CenterBottom = 8,

            /// <summary>
            /// 右下角
            /// </summary>
            RightBottom = 9,
        }

        #endregion WatermarkPosition enum

        #endregion 公共枚举

        #region 公共方法

        /// <summary>
        /// 字体号数数组
        /// </summary>
        private readonly int[] _sizes = { 48, 32, 16, 8, 6, 4 };

        /// <summary>
        /// 添加文字水印并生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径(物理路径)</param>
        /// <param name="savePath">保存的图片路径(物理路径)</param>
        /// <param name="text">水印的文字</param>
        /// <param name="fontFamily">水印文字的字体</param>
        /// <param name="fontSize">水印文字的号数</param>
        /// <param name="position">水印位置</param>
        /// <param name="isBold">是否加粗</param>
        /// <param name="textColor">水印文字的颜色</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="mode">生成缩略图的模式</param>
        /// <param name="type">保存缩略图的格式</param>
        public void MakeWordWatermarkAndThumbnail(string originalImagePath, string savePath, string text,
            FontFamily fontFamily, float? fontSize, WatermarkPosition position,
            bool isBold, Color textColor, int width, int height,
            ThumbnailMode mode, ThumbnailType type)
        {
            //添加水印
            MakeWordWatermark(originalImagePath, savePath, text, fontFamily, fontSize, position, isBold, textColor);

            //获取图片名称
            var fileName = Path.GetFileNameWithoutExtension(savePath);
            if (fileName == null) return;
            var thImagePath = savePath.Replace(fileName, "th_" + fileName);

            //生成缩略图
            //以添加水印的图片为准
            MakeThumbnail(savePath, thImagePath, width, height, mode, type);
        }

        /// <summary>
        /// 添加图片水印并生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径(物理路径)</param>
        /// <param name="savePath">保存的图片路径(物理路径)</param>
        /// <param name="waterImagePath">水印源图片路径(物理路径)</param>
        /// <param name="position">水印位置</param>
        /// <param name="isTransparence">是否半透明</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="mode">生成缩略图的模式</param>
        /// <param name="type">保存缩略图的格式</param>
        public void MakeImageWatermarkAndThumbnail(string originalImagePath, string savePath, string waterImagePath,
            WatermarkPosition position, bool isTransparence, int width,
            int height, ThumbnailMode mode, ThumbnailType type)
        {
            //水印
            MakeImageWatermark(originalImagePath, savePath, waterImagePath, position, isTransparence);

            //获取图片名称
            var fileName = Path.GetFileNameWithoutExtension(savePath);
            if (fileName == null) return;
            var thImagePath = savePath.Replace(fileName, "th_" + fileName);

            //缩略图
            MakeThumbnail(savePath, thImagePath, width, height, mode, type);
        }

        /// <summary>
        /// 计算水印坐标位置.
        /// </summary>
        /// <param name="image"></param>
        /// <param name="watermarkWidth"></param>
        /// <param name="watermarkHeight"></param>
        /// <param name="position"></param>
        /// <param name="markx"></param>
        /// <param name="marky"></param>
        private void SetMarkPosition(Image image, int watermarkWidth, int watermarkHeight, WatermarkPosition position,
            ref int markx, ref int marky)
        {
            var width = image.Width / 3;
            var height = image.Height / 3;
            switch (position)
            {
                case WatermarkPosition.LeftTop:
                    markx = width / 2;
                    marky = height / 2;
                    break;
                case WatermarkPosition.CenterTop:
                    markx = (image.Width - watermarkWidth) / 2;
                    marky = height / 2;
                    break;
                case WatermarkPosition.RightTop:
                    markx = width * 2 + width / 2 - watermarkWidth / 2;
                    marky = height / 2;
                    break;
                case WatermarkPosition.LeftMiddle:
                    markx = width / 2;
                    marky = (image.Height - watermarkHeight) / 2;
                    break;
                case WatermarkPosition.CenterMiddle:
                    markx = (image.Width - watermarkWidth) / 2;
                    marky = (image.Height - watermarkHeight) / 2;
                    break;
                case WatermarkPosition.RightMiddle:
                    markx = width * 2 + width / 2 - watermarkWidth / 2;
                    marky = (image.Height - watermarkHeight) / 2;
                    break;
                case WatermarkPosition.LeftBottom:
                    markx = width / 2;
                    marky = height * 2 + height / 2 - watermarkHeight / 2;
                    break;
                case WatermarkPosition.CenterBottom:
                    markx = (image.Width - watermarkWidth) / 2;
                    marky = height * 2 + height / 2 - watermarkHeight / 2;
                    break;
                case WatermarkPosition.RightBottom:
                    markx = width * 2 + width / 2 - watermarkWidth / 2;
                    marky = height * 2 + height / 2 - watermarkHeight / 2;
                    break;
            }
        }

        #endregion 公共方法

        /// <summary>
        /// 会产生graphics异常的PixelFormat
        /// </summary>
        private static readonly PixelFormat[] IndexedPixelFormats =
        {
            PixelFormat.Undefined, PixelFormat.DontCare,
            PixelFormat.Format16bppArgb1555, PixelFormat.Format1bppIndexed, PixelFormat.Format4bppIndexed,
            PixelFormat.Format8bppIndexed
        };

        /// <summary>
        /// 判断图片的PixelFormat 是否在 引发异常的 PixelFormat 之中
        /// 无法从带有索引像素格式的图像创建graphics对象
        /// </summary>
        /// <param name="imgPixelFormat">原图片的PixelFormat</param>
        /// <returns></returns>
        private static bool IsPixelFormatIndexed(PixelFormat imgPixelFormat)
        {
            return IndexedPixelFormats.Contains(imgPixelFormat);
        }

        #region 缩略图

        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径(物理路径)</param>
        /// <param name="thumbnailPath">缩略图保存路径(物理路径)</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="mode">生成缩略图的模式</param>
        /// <param name="type">保存缩略图的格式</param>
        public void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height,
            ThumbnailMode mode, ThumbnailType type)
        {
            var originalImage = Image.FromFile(originalImagePath);

            var towidth = width;
            var toheight = height;

            var x = 0;
            var y = 0;
            var ow = originalImage.Width;
            var oh = originalImage.Height;

            #region 根据缩略图的模式计算宽与高

            switch (mode)
            {
                case ThumbnailMode.Wh:
                    break;
                case ThumbnailMode.W:
                    toheight = originalImage.Height * width / originalImage.Width;
                    break;
                case ThumbnailMode.H:
                    towidth = originalImage.Width * height / originalImage.Height;
                    break;
                case ThumbnailMode.Cut:
                    if (originalImage.Width / (double)originalImage.Height > towidth / (double)toheight)
                    {
                        oh = originalImage.Height;
                        ow = originalImage.Height * towidth / toheight;
                        y = 0;
                        x = (originalImage.Width - ow) / 2;
                    }
                    else
                    {
                        ow = originalImage.Width;
                        oh = originalImage.Width * height / towidth;
                        x = 0;
                        y = (originalImage.Height - oh) / 2;
                    }
                    break;
                case ThumbnailMode.Db:
                    if (originalImage.Width / (double)towidth < originalImage.Height / (double)toheight)
                    {
                        toheight = height;
                        towidth = originalImage.Width * height / originalImage.Height;
                    }
                    else
                    {
                        towidth = width;
                        toheight = originalImage.Height * width / originalImage.Width;
                    }
                    break;
            }

            #endregion 根据缩略图的模式计算宽与高

            //新建一个bmp图片
            Image bitmap = new Bitmap(towidth, toheight);

            //新建一个画板
            var g = Graphics.FromImage(bitmap);

            //设置高质量插值法
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;

            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = SmoothingMode.HighQuality;

            //清空画布并以透明背景色填充
            g.Clear(Color.Transparent);

            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
                new Rectangle(x, y, ow, oh),
                GraphicsUnit.Pixel);

            try
            {
                //关键质量控制
                //获取系统编码类型数组,包含了jpeg,bmp,png,gif,tiff
                var icis = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo ici = null;
                foreach (
                    var i in
                        icis.Where(
                            i => i.MimeType == "image/jpeg" || i.MimeType == "image/bmp" || i.MimeType == "image/png" ||
                                 i.MimeType == "image/gif"))
                {
                    ici = i;
                }
                var ep = new EncoderParameters(1);
                ep.Param[0] = new EncoderParameter(Encoder.Quality, 100);
                //保存缩略图
                if (ici != null) bitmap.Save(thumbnailPath, ici, ep);
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }
        }

        #endregion 缩略图

        #region 水印

        /// <summary>
        /// 生成文字水印
        /// </summary>
        /// <param name="originalImagePath">源图路径(物理路径)</param>
        /// <param name="savePath">保存的图片路径(物理路径)</param>
        /// <param name="text">水印文字</param>
        /// <param name="fontFamily">水印文字的字体</param>
        /// <param name="fontSize">水印文字的字体号数</param>
        /// <param name="position">水印位置</param>
        /// <param name="isBold">是否加粗</param>
        /// <param name="textColor">水印文字的字体颜色</param>
        public void MakeWordWatermark(string originalImagePath, string savePath, string text, FontFamily fontFamily,
            float? fontSize, WatermarkPosition position, bool isBold, Color textColor)
        {
            var originalImage = Image.FromFile(originalImagePath);

            //根据源图片生成新的Bitmap对象作为作图区，为了给gif图片添加水印，才有此周折
            var bitmap = new Bitmap(originalImage.Width, originalImage.Height, PixelFormat.Format32bppArgb);
            //设置新建位图得分辨率
            bitmap.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);
            //创建Graphics对象，以对该位图进行操作
            var g = Graphics.FromImage(bitmap);
            //消除锯齿
            g.SmoothingMode = SmoothingMode.AntiAlias;
            //将原图拷贝到作图区
            g.DrawImage(originalImage, new Rectangle(0, 0, originalImage.Width, originalImage.Height), 0, 0,
                originalImage.Width, originalImage.Height, GraphicsUnit.Pixel);

            //声明字体对象
            Font cFont = null;
            //用来测试水印文本长度得尺子
            var size = new SizeF();
            if (!fontSize.HasValue)
            {
                //探测出一个适合图片大小得字体大小，以适应水印文字大小得自适应
                for (var i = 0; i < 6; i++)
                {
                    //创建一个字体对象
                    //是否加粗
                    cFont = !isBold ? new Font(fontFamily, _sizes[i], FontStyle.Regular) : new Font(fontFamily, _sizes[i], FontStyle.Bold);
                    //测量文本大小
                    size = g.MeasureString(text, cFont);
                    //匹配第一个符合要求得字体大小
                    if ((ushort)size.Width < (ushort)originalImage.Width)
                    {
                        break;
                    }
                }
            }
            else
            {
                cFont = !isBold ? new Font(fontFamily, fontSize.Value, FontStyle.Regular) : new Font(fontFamily, fontSize.Value, FontStyle.Bold);
            }
            //设置水印坐标位置.
            var markx = 5;
            var marky = 5;

            SetMarkPosition(originalImage, (int)size.Width, (int)size.Height, position, ref markx, ref marky);
            //创建刷子对象，准备给图片写上文字
            Brush brush = new SolidBrush(textColor);
            //在指定得位置写上文字
            g.DrawString(text, cFont, brush, markx, marky);
            try
            {
                //默认60%的图片质量, 图片较模糊, 论坛12楼 http://topic.csdn.net/u/20090819/14/c302cba0-a70a-43f7-a265-6e91c55a2f6f.html
                bitmap.Save(savePath, ImageFormat.Jpeg);
                //以全质量重新保存图片
                var p = new EncoderParameter(Encoder.Quality, 100L);
                var ps = new EncoderParameters();
                ps.Param[0] = p;

                var cInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.MimeType == "image/jpeg");
                if (cInfo == null) return;
                File.Delete(savePath);
                bitmap.Save(savePath, cInfo, ps);
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                //释放Graphics对象
                g.Dispose();
            }
        }

        /// <summary>
        /// 生成图片水印.
        /// </summary>
        /// <param name="originalImagePath">源图路径（物理路径）</param>
        /// <param name="savePath">保存的图片路径(物理路径)</param>
        /// <param name="waterImagePath">水印源图路径（物理路径）</param>
        /// <param name="position">水印位置枚举</param>
        /// <param name="isTransparence">是否半透明</param>
        public bool MakeImageWatermark(string originalImagePath, string savePath, string waterImagePath,
            WatermarkPosition position, bool isTransparence)
        {
            var originalImage = Image.FromFile(originalImagePath);

            //获得水印图像
            var markImg = Image.FromFile(waterImagePath);

            if (originalImage.Width < markImg.Width || originalImage.Height < markImg.Height)
                return false;

            //创建颜色矩阵
            var transparence = isTransparence ? 0.5f : 1.0f;
            float[][] ptsArray =
            {
                new float[] {1, 0, 0, 0, 0},
                new float[] {0, 1, 0, 0, 0},
                new float[] {0, 0, 1, 0, 0},
                new[] {0, 0, 0, transparence, 0}, //注意：此处为0.0f为完全透明，1.0f为完全不透明
                new float[] {0, 0, 0, 0, 1}
            };
            var colorMatrix = new ColorMatrix(ptsArray);
            //新建一个Image属性
            var imageAttributes = new ImageAttributes();
            //将颜色矩阵添加到属性
            imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default,
                ColorAdjustType.Default);
            //生成位图作图区
            var bitmap = new Bitmap(originalImage.Width, originalImage.Height, PixelFormat.Format32bppArgb);
            //设置分辨率
            bitmap.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);
            //创建Graphics
            var g = Graphics.FromImage(bitmap);
            //消除锯齿
            g.SmoothingMode = SmoothingMode.AntiAlias;
            //拷贝原图到作图区
            g.DrawImage(originalImage, new Rectangle(0, 0, originalImage.Width, originalImage.Height), 0, 0,
                originalImage.Width, originalImage.Height, GraphicsUnit.Pixel);

            var markx = 5;
            var marky = 5;
            SetMarkPosition(originalImage, markImg.Width, markImg.Height, position, ref markx, ref marky);

            //添加水印
            g.DrawImage(markImg, new Rectangle(markx, marky, markImg.Width, markImg.Height), 0, 0, markImg.Width,
                markImg.Height, GraphicsUnit.Pixel, imageAttributes);
            try
            {
                //默认60%的图片质量, 图片较模糊, 论坛12楼 http://topic.csdn.net/u/20090819/14/c302cba0-a70a-43f7-a265-6e91c55a2f6f.html
                bitmap.Save(savePath, ImageFormat.Jpeg);
                //以全质量重新保存图片
                var p = new EncoderParameter(Encoder.Quality, 100L);
                var ps = new EncoderParameters();
                ps.Param[0] = p;

                var cInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.MimeType == "image/jpeg");
                if (cInfo != null)
                {
                    File.Delete(savePath);
                    bitmap.Save(savePath, cInfo, ps);
                }
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }

            return true;
        }



        /// <summary>
        /// 按比例生成文字水印图
        /// </summary>
        /// <param name="originalImagePath">图片路径</param>
        /// <param name="savePath">保存路径</param>
        /// <param name="text">水印文字</param>
        /// <param name="fontFamily">水印字体</param>
        /// <param name="fontColor">文字颜色</param>
        /// <param name="position">水印位置</param>
        /// <param name="proportion">比例大小, 小于整数1</param>
        /// <param name="transparency">水印透明度（0-255）</param>
        public void MakeTextMark(string originalImagePath,
            string savePath,
            string text,
            FontFamily fontFamily,
            Color fontColor,
            WatermarkPosition position,
            float? proportion, int transparency)
        {
            var img = Image.FromFile(originalImagePath);

            if (IsPixelFormatIndexed(img.PixelFormat))
            {
                var bmp = new Bitmap(img.Width, img.Height, PixelFormat.Format32bppArgb);
                var g = Graphics.FromImage(bmp);
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.CompositingQuality = CompositingQuality.HighQuality;
                g.DrawImage(img, 0, 0);


                var originalImageWidth = img.Width;

                var drawWidth = Convert.ToInt32(originalImageWidth * proportion);

                var fontSize = drawWidth / text.Length; //原定的字体大小
                var drawFont = new Font(fontFamily, fontSize, FontStyle.Regular, GraphicsUnit.Pixel);
                SizeF crSize = g.MeasureString(text, drawFont);

                float xpos = 0;
                float ypos = 0;

                switch (position)
                {
                    case WatermarkPosition.LeftTop:
                        xpos = img.Width * (float).01;
                        ypos = img.Height * (float).01;
                        break;
                    case WatermarkPosition.CenterTop:
                        xpos = (img.Width * (float).50) - (crSize.Width / 2);
                        ypos = img.Height * (float).01;
                        break;
                    case WatermarkPosition.RightTop:
                        xpos = (img.Width * (float).99) - crSize.Width;
                        ypos = img.Height * (float).01;
                        break;
                    case WatermarkPosition.LeftMiddle:
                        xpos = img.Width * (float).01;
                        ypos = (img.Height * (float).50) - (crSize.Height / 2);
                        break;
                    case WatermarkPosition.CenterMiddle:
                        xpos = (img.Width * (float).50) - (crSize.Width / 2);
                        ypos = (img.Height * (float).50) - (crSize.Height / 2);
                        break;
                    case WatermarkPosition.RightMiddle:
                        xpos = (img.Width * (float).99) - crSize.Width;
                        ypos = (img.Height * (float).50) - (crSize.Height / 2);
                        break;
                    case WatermarkPosition.LeftBottom:
                        xpos = img.Width * (float).01;
                        ypos = (img.Height * (float).99) - crSize.Height;
                        break;
                    case WatermarkPosition.CenterBottom:
                        xpos = (img.Width * (float).50) - (crSize.Width / 2);
                        ypos = (img.Height * (float).99) - crSize.Height;
                        break;
                    case WatermarkPosition.RightBottom:
                        xpos = (img.Width * (float).99) - crSize.Width;
                        ypos = (img.Height * (float).99) - crSize.Height;
                        break;
                }
                Brush brush = new SolidBrush(Color.FromArgb(transparency, fontColor.R, fontColor.G, fontColor.B));
                //g.DrawString(watermarkText, drawFont, new SolidBrush(Color.White), xpos + 1, ypos + 1);文字阴影 www.keleyi.com
                g.DrawString(text, drawFont, brush, xpos, ypos);

                var codecs = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo ici = null;
                foreach (var codec in codecs)
                {
                    if (codec.MimeType.IndexOf("jpeg", StringComparison.Ordinal) > -1)
                        ici = codec;
                }
                var encoderParams = new EncoderParameters();
                var qualityParam = new long[1];
                var quality = 99; //加水印后的质量0~100,数字越大质量越高
                if (quality < 0 || quality > 100)
                    quality = 80;

                qualityParam[0] = quality;

                var encoderParam = new EncoderParameter(Encoder.Quality,
                    qualityParam);
                encoderParams.Param[0] = encoderParam;

                if (ici != null)
                    img.Save(savePath, ici, encoderParams);
                else
                    img.Save(savePath);

                g.Dispose();
                img.Dispose();
            }
            else
            {
                var g = Graphics.FromImage(img);
                var originalImageWidth = img.Width;

                var drawWidth = Convert.ToInt32(originalImageWidth * proportion);

                var fontSize = drawWidth / text.Length; //原定的字体大小
                var drawFont = new Font(fontFamily, fontSize, FontStyle.Regular, GraphicsUnit.Pixel);
                SizeF crSize = g.MeasureString(text, drawFont);

                float xpos = 0;
                float ypos = 0;

                switch (position)
                {
                    case WatermarkPosition.LeftTop:
                        xpos = img.Width * (float).01;
                        ypos = img.Height * (float).01;
                        break;
                    case WatermarkPosition.CenterTop:
                        xpos = (img.Width * (float).50) - (crSize.Width / 2);
                        ypos = img.Height * (float).01;
                        break;
                    case WatermarkPosition.RightTop:
                        xpos = (img.Width * (float).99) - crSize.Width;
                        ypos = img.Height * (float).01;
                        break;
                    case WatermarkPosition.LeftMiddle:
                        xpos = img.Width * (float).01;
                        ypos = (img.Height * (float).50) - (crSize.Height / 2);
                        break;
                    case WatermarkPosition.CenterMiddle:
                        xpos = (img.Width * (float).50) - (crSize.Width / 2);
                        ypos = (img.Height * (float).50) - (crSize.Height / 2);
                        break;
                    case WatermarkPosition.RightMiddle:
                        xpos = (img.Width * (float).99) - crSize.Width;
                        ypos = (img.Height * (float).50) - (crSize.Height / 2);
                        break;
                    case WatermarkPosition.LeftBottom:
                        xpos = img.Width * (float).01;
                        ypos = (img.Height * (float).99) - crSize.Height;
                        break;
                    case WatermarkPosition.CenterBottom:
                        xpos = (img.Width * (float).50) - (crSize.Width / 2);
                        ypos = (img.Height * (float).99) - crSize.Height;
                        break;
                    case WatermarkPosition.RightBottom:
                        xpos = (img.Width * (float).99) - crSize.Width;
                        ypos = (img.Height * (float).99) - crSize.Height;
                        break;
                }
                Brush brush = new SolidBrush(Color.FromArgb(transparency, fontColor.R, fontColor.G, fontColor.B));
                //g.DrawString(watermarkText, drawFont, new SolidBrush(Color.White), xpos + 1, ypos + 1);文字阴影 www.keleyi.com
                g.DrawString(text, drawFont, brush, xpos, ypos);

                var codecs = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo ici = null;
                foreach (var codec in codecs)
                {
                    if (codec.MimeType.IndexOf("jpeg", StringComparison.Ordinal) <= -1) continue;
                    ici = codec;
                }
                var encoderParams = new EncoderParameters();
                var qualityParam = new long[1];
                var quality = 99; //加水印后的质量0~100,数字越大质量越高
                if (quality < 0 || quality > 100)
                    quality = 80;

                qualityParam[0] = quality;

                var encoderParam = new EncoderParameter(Encoder.Quality,
                    qualityParam);
                encoderParams.Param[0] = encoderParam;

                if (ici != null)
                    img.Save(savePath, ici, encoderParams);
                else
                    img.Save(savePath);

                g.Dispose();
                img.Dispose();
            }
        }

        /// <summary>
        /// 按比例生成图片水印图
        /// </summary>
        /// <param name="originalImagePath">图片路径</param>
        /// <param name="savePath">保存路径</param>
        /// <param name="markImagePath">水印底图的存放路径</param>
        /// <param name="tempMarkImagePath">按比例生成临时水印底图的存放路径</param>
        /// <param name="position">水印位置</param>
        /// <param name="proportion">比例大小, 小于整数1</param>
        public void MakeImageMark(string originalImagePath,
            string savePath,
            string markImagePath,
            string tempMarkImagePath,
            WatermarkPosition position,
            float? proportion)
        {
            var originalImage = Image.FromFile(originalImagePath);

            var markImage = Image.FromFile(markImagePath);

            int finalMarkHeight; //最终水印的高度
            int finalMarkWidth; //最终水印的宽度

            if (originalImage.Height > originalImage.Width)
            {
                //以宽度为准计算比例
                finalMarkWidth = Convert.ToInt32(originalImage.Width * proportion);
                finalMarkHeight = markImage.Height * finalMarkWidth / markImage.Width;
            }
            else
            {
                //以高度为准计算比例
                finalMarkHeight = Convert.ToInt32(originalImage.Height * proportion);
                finalMarkWidth = markImage.Width * finalMarkHeight / markImage.Height;
            }

            var bitmap = new Bitmap(finalMarkWidth, finalMarkHeight);
            var g = Graphics.FromImage(bitmap);
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.Clear(Color.Transparent);
            g.DrawImage(markImage,
                new Rectangle(0, 0, finalMarkWidth, finalMarkHeight),
                new Rectangle(0, 0, markImage.Width, markImage.Height),
                GraphicsUnit.Pixel
                );

            try
            {
                //将水印图计算比例后, 暂时存入待存放路径
                var arrCodecInfo = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo codecInfo = null;
                foreach (var i in arrCodecInfo.Where(i => i.MimeType == "image/jpeg" ||
                                                                     i.MimeType == "image/bmp" ||
                                                                     i.MimeType == "image/png" ||
                                                                     i.MimeType == "image/gif"))
                {
                    codecInfo = i;
                }

                var ep = new EncoderParameters(1);
                ep.Param[0] = new EncoderParameter(Encoder.Quality, 100);
                if (codecInfo != null) bitmap.Save(tempMarkImagePath, codecInfo, ep);

                //重新取出水印图, 待印到原图
                markImage = Image.FromFile(tempMarkImagePath);

                #region 计算绘制的位置

                var positionX = 0;
                var positionY = 0;
                const int padding = 3;

                //垂直居顶 - Y
                const int valignTop = padding;
                //垂直居中 - Y
                var valignMiddle = (originalImage.Height - (padding * 2) - markImage.Height) / 2;
                //垂直居底 - Y
                var valignBottom = originalImage.Height - (padding * 2) - markImage.Height;
                //水平居左 - X
                const int alignLeft = padding;
                //水平居中 - X  
                var alignCenter = (originalImage.Width - (padding * 2) - markImage.Width) / 2;
                //水平居右 - X
                var alignRight = originalImage.Width - (padding * 2) - markImage.Width;

                switch (position)
                {
                    case WatermarkPosition.LeftTop:
                        positionX = alignLeft;
                        positionY = valignTop;
                        break;
                    case WatermarkPosition.LeftMiddle:
                        positionX = alignLeft;
                        positionY = valignMiddle;
                        break;
                    case WatermarkPosition.LeftBottom:
                        positionX = alignLeft;
                        positionY = valignBottom;
                        break;
                    case WatermarkPosition.CenterTop:
                        positionX = alignCenter;
                        positionY = valignTop;
                        break;
                    case WatermarkPosition.CenterMiddle:
                        positionX = alignCenter;
                        positionY = valignMiddle;
                        break;
                    case WatermarkPosition.CenterBottom:
                        positionX = alignCenter;
                        positionY = valignBottom;
                        break;
                    case WatermarkPosition.RightTop:
                        positionX = alignRight;
                        positionY = valignTop;
                        break;
                    case WatermarkPosition.RightMiddle:
                        positionX = alignRight;
                        positionY = valignMiddle;
                        break;
                    case WatermarkPosition.RightBottom:
                        positionX = alignRight;
                        positionY = valignBottom;
                        break;
                }

                #endregion 计算绘制的位置

                bitmap = new Bitmap(originalImage.Width, originalImage.Height, PixelFormat.Format32bppArgb);
                bitmap.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);
                g = Graphics.FromImage(bitmap);
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.DrawImage(originalImage,
                    new Rectangle(0, 0, originalImage.Width, originalImage.Height),
                    0, 0,
                    originalImage.Width,
                    originalImage.Height,
                    GraphicsUnit.Pixel);
                g.DrawImage(markImage,
                    new Rectangle(positionX, positionY, markImage.Width, markImage.Height),
                    0, 0,
                    markImage.Width,
                    markImage.Height,
                    GraphicsUnit.Pixel
                    );

                bitmap.Save(savePath, ImageFormat.Jpeg);

                //默认60%的图片质量, 图片较模糊, 论坛12楼 http://topic.csdn.net/u/20090819/14/c302cba0-a70a-43f7-a265-6e91c55a2f6f.html
                bitmap.Save(savePath, ImageFormat.Jpeg);
                //以全质量重新保存图片
                var p = new EncoderParameter(Encoder.Quality, 100L);
                var ps = new EncoderParameters();
                ps.Param[0] = p;

                var cInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.MimeType == "image/jpeg");
                if (cInfo != null)
                {
                    File.Delete(savePath);
                    bitmap.Save(savePath, cInfo, ps);
                }
            }
            finally
            {
                originalImage.Dispose();
                markImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }

        }


        #endregion 水印


        /// <summary>
        /// 转换图片原路径为缩略图路径
        /// </summary>
        /// <param name="imagePath"></param>
        /// <returns></returns>
        public string GetThumbImgPath(object imagePath)
        {
            try
            {
                var path = imagePath.ToStr();
                if (!path.IsEmpty())
                {
                    var prev = path.Substring(0, path.LastIndexOf("/", StringComparison.Ordinal) + 1);
                    path = path.Substring(path.LastIndexOf("/", StringComparison.Ordinal) + 1);
                    if (path.StartsWith("th_"))
                    {
                        path = path.Substring("th_".Length);
                    }
                    return prev + path;
                }
                return string.Empty;
            }
            catch
            {
                return string.Empty;
            }
        }

    }
}